import java.rmi.Naming; 
import java.rmi.RemoteException; 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException; 
import java.rmi.NotBoundException; 

public class Manager{

	public final static String RmiURL = "rmi://localhost/";
	public final static String RemoteService = "BookingService";
	private BookingService bookingServer;
	private ClientInterface me;
    private final static String commands_ = "view,reserve,delete,add,detail,remove,exit";

	/**
	 * Constructs a manager client.
	 * @param b_service used to initialize a reference to the remote server object.
	 */
	public Manager(BookingService b_service){
		this.setBookingservice(b_service);
		
		//register myself for the notifications
		try 
		{
			me = new ClientInterfaceImp();
			bookingServer.registerForNotifications( me );
		} 
		catch (RemoteException e) 
		{
			//something wrong happened 
		}
		
	}
	
	
	private String view() {
		try 
		{
			return bookingServer.view();
		} 
		catch (RemoteException e) 
		{
			e.printStackTrace();
			return "Problem fetching events.\n";
		}
	}
	

	private String delete(Integer integer, Integer integer2) {
		try 
		{
			if( bookingServer.eventExists(integer) )
			{
				if( bookingServer.reservationExists(integer2) )
				{
					//wrap the systems standard in file descriptor with an input stream reader object
			        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
					System.out.println("Are you sure you want to delete this reservation?(yes/no)\n");
					
					if( stdIn.readLine().equals("yes") )
					{
						return bookingServer.delete(integer, integer2);
					}
					else
					{
						return "Did not delete reservation.\n";
					}
				}
				else
				{
					return "Error. Reservation number is not valid!\n";
				}
			}
			else
			{
				return "Error. Event does not exist\n";
			}
			
		} 
		catch (RemoteException e) 
		{
			e.printStackTrace();
			return "Problem deleting reservation.\n";
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
			return "Problem with IO.\n";
		}
	}
	
	private String reserve(Integer integer, Integer integer2, String string) {
		try 
		{
			return bookingServer.reserve( integer, integer2, string);
		} 
		catch (RemoteException e) 
		{
			e.printStackTrace();
			return "Problem making reservation.\n";
		}
	}
	
	private String detail(Integer integer) {
		try 
		{
			return bookingServer.detail( integer );
		} 
		catch (RemoteException e) 
		{
			e.printStackTrace();
			return "Problem fetching detail for event.\n";
		}
	}
	
	
	private String remove(Integer integer) {
		
		try 
		{
			if( bookingServer.eventExists(integer) )
			{
				
				//wrap the systems standard in file descriptor with an input stream reader object
			    BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
				System.out.println("Are you sure you want to remove this event?(yes/no)\n");
					
				if( stdIn.readLine().equals("yes") )
				{
					return bookingServer.remove( integer );
				}
				else
				{
					return "Did not remove event.\n";
				}
				
			}	
			else
			{
				return "Error. Event does not exist\n";
			}
			
		} 
		catch (RemoteException e) 
		{
			e.printStackTrace();
			return "Problem removing event.\n";
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
			return "Problem with IO.\n";
		}
		
	}
	
	private String add(String string, Integer integer) {
		try 
		{
			return bookingServer.add( string,  integer );
		} 
		catch (RemoteException e) 
		{
			e.printStackTrace();
			return "Problem adding event.\n";
		}
	}
		
		
	public void setBookingservice(BookingService bookingservice) {
			this.bookingServer = bookingservice;
	}
	
	public BookingService getBookingservice() {
			return bookingServer;
	}
		
	public String getCommand(String theCommand) {
		/*	VIEW
		 * 
		 */
		//convert command to all lover case, and split into tokens
	    String[] command = theCommand.toLowerCase().split("\\s");
	    if(command[0].matches("view"))
	    {
	    	return this.view();
	    }
	    
	    /* RESERVE
	     * 
	     */
	    //reserve event_number space_amount person_name,  e.g. reserve 5 10 Sol
	    if(command[0].matches("reserve"))
	    { 
	    	String regex = "reserve[\\s][\\d]+[\\s][\\d]+[\\s][\\w]+";
	    	//if the input matches the correct criterion
	    	if(theCommand.matches(regex))
	    	{
	    		//call the reserve function
	    		 return this.reserve(new Integer(command[1]), new Integer(command[2]), new String(command[3]));
	    	}
	    	else
	    	{
	    		return "Invalid format: reserve <event_number> <space_amount> <person_name>";
	    	}
	    }
	    
	    /* DELETE
	     *
	     * User Input: delete event_number confirmation_number, e.g. delete 5 5111
	     */
	    if(command[0].matches("delete"))
	    { 
	    	String regex = "delete[\\s][\\d]+[\\s][\\d]+";
	    	//if the input matches the correct criterion
	    	if(theCommand.matches(regex))
	    	{
	    		//call the reserve function
	    		return this.delete(new Integer(command[1]), new Integer(command[2]));
	    	}
	    	else
	    	{
	    		return "Invalid format: delete <event_number> <confirmation_number>";
	    	}
	    }
	    
	    /* ADD
	     * 
	     * add description request_space ,e.g.add Lincoln Park Concert 5000
	     */
	    if(command[0].matches("add"))
	    { 
	    	//TODO: Implement 3 line command
	    	String regex = "add[\\s][\\w]+[\\s][\\d]+";
	    	//if the input matches the correct criterion
	    	if(theCommand.matches(regex))
	    	{
	    		//call the reserve function
	    		return this.add(new String(command[1]), new Integer(command[2]));
	    	}
	    	else
	    	{
	    		return "Invalid format: add\n<description>\n<request_space>";
	    	}
	    }
	    
	    /* REMOVE
	     * 
	     * remove event_number, e.g. remove 100 
	     */
	    if(command[0].matches("remove"))
	    { 
	    	String regex = "remove[\\s][\\d]+";
	    	//if the input matches the correct criterion
	    	if(theCommand.matches(regex))
	    	{
	    		//call the reserve function
	    		return this.remove(new Integer(command[1]));
	    	}
	    	else
	    	{
	    		return "Invalid format: remove <event_number>";
	    	}
	    }
	    
	    /* DETAIL
	     * 
	     * detail event_number, e.g. detail 100
	     */
	    
	    if(command[0].matches("detail"))
	    { 
	    	String regex = "detail[\\s][\\d]+";
	    	//if the input matches the correct criterion
	    	if(theCommand.matches(regex))
	    	{
	    		//call the reserve function
	    		return this.detail(new Integer(command[1]));
	    	}
	    	else
	    	{
	    		return "Invalid format: detail <event_number>";
	    	}
	    }
	    
	    return "Error: Unknown command!";
	}
				
	public static void main(String[] args) {
			
		//wrap the systems standard in file descriptor with an input stream reader object
        BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
        
		try { 
			 //locating the service to use	
			Manager Manager = new Manager((BookingService)Naming.lookup(RmiURL + RemoteService));
		    System.out.println ("Type (\"exit\" to exit)");
			System.out.println("Command List: " + commands_);
            String input ="";
            while((input = stdIn.readLine())!=null)
            {
            	
            	if(input.equals("")) continue;
        	 
        	 	if(input.toLowerCase().equals("exit")) break;
        	 
        	 	//send command and print response.
        	 	System.out.println(Manager.getCommand(input));
             }
             System.out.println("GoodBye!");
             System.exit(0);
        } 
        catch (MalformedURLException e) 
        { 
			e.printStackTrace();

        } 
        catch (RemoteException e) 
        { 
			e.printStackTrace();

        } 
        catch (NotBoundException e) 
        { 
			e.printStackTrace();

        } 
        catch (IOException e) 
        {
			e.printStackTrace();
		} 
    }
			
}
